﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

namespace Sherwood
{
    public static class XmlExtensionMethods
    {
        public static void WriteNodeTo(this XmlReader reader, XmlWriter writer)
        {
            if (reader == null)
                throw new ArgumentNullException("reader");
            if (writer == null)
                throw new ArgumentNullException("writer");

            switch (reader.NodeType)
            {
                case XmlNodeType.Element:
                    writer.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
                    writer.WriteAttributes(reader, true);
                    if (reader.IsEmptyElement)
                        writer.WriteEndElement();
                    break;

                case XmlNodeType.Text:
                    writer.WriteString(reader.Value);
                    break;

                case XmlNodeType.Whitespace:
                case XmlNodeType.SignificantWhitespace:
                    writer.WriteWhitespace(reader.Value);
                    break;

                case XmlNodeType.CDATA:
                    writer.WriteCData(reader.Value);
                    break;

                case XmlNodeType.EntityReference:
                    writer.WriteEntityRef(reader.Name);
                    break;

                case XmlNodeType.XmlDeclaration:
                case XmlNodeType.ProcessingInstruction:
                    writer.WriteProcessingInstruction(reader.Name, reader.Value);
                    break;

                case XmlNodeType.DocumentType:
                    writer.WriteDocType(reader.Name, reader.GetAttribute("PUBLIC"), reader.GetAttribute("SYSTEM"), reader.Value);
                    break;

                case XmlNodeType.Comment:
                    writer.WriteComment(reader.Value);
                    break;

                case XmlNodeType.EndElement:
                    writer.WriteFullEndElement();
                    break;
            }
        }

        /// <summary>
        /// This method ensures that the output string has only
        /// valid XML unicode characters as specified by the
        /// XML 1.0 standard. For reference, please see
        /// <a href="http://www.w3.org/TR/2000/REC-xml-20001006#NT-Char">the
        /// standard</a>. This method will return an empty
        /// string if the input is null or empty.
        /// </summary>
        public static string StripNonValidXmlCharacters(this String s)
        {
            var result = new StringBuilder(); // Used to hold the output.

            if (string.IsNullOrEmpty(s)) return string.Empty;// vacancy test.

            foreach (var current in s)
            {
                if ((current == 0x9) ||
                    (current == 0xA) ||
                    (current == 0xD) ||
                    ((current >= 0x20) && (current <= 0xD7FF)) ||
                    ((current >= 0xE000) && (current <= 0xFFFD)) ||
                    ((current >= 0x10000) && (current <= 0x10FFFF)))
                    result.Append(current);
            }
            return result.ToString();
        }
    }
}
